package models

import (
	"database/sql"
	"fmt"
	"github.com/astaxie/beego/logs"
	"github.com/astaxie/beego/orm"
	"smart_home/api/device"
	"time"
	"tools"
)

type Delay struct {
	Id         string `orm:"column(id);pk" json:"id" form:"id"`
	Sta        string `orm:"column(sta)" json:"sta" form:"sta"`
	Start      int    `orm:"column(start)" json:"start" form:"start"`
	End        int    `orm:"column(end)" json:"end" form:"end"`
	State      int    `orm:"column(state)" json:"state" form:"state"`
	Loop       int    `orm:"column(loop)" json:"loop" form:"loop"`
	Time       int64  `orm:"column(time)" json:"time" form:"time"`
	Order      int    `orm:"column(order)" json:"order" form:"order"`
	UpdateTime int64  `orm:"column(update_time)" json:"update_time"`
}

func init() {
	orm.RegisterModel(new(Delay))
}

func (m *Delay) TableName() string {
	return "delay"
}

func NewDelay() *Delay {
	return &Delay{}
}

func GetDelayById(id string) (*Delay, error) {
	dl := &Delay{Id: id}
	err := orm.NewOrm().Read(dl)
	if err == orm.ErrNoRows {
		return nil, nil
	}
	if err != nil {
		logs.Error("GetDelayById error:", err)
		return nil, err
	}
	return dl, nil
}

// 添加延时
func AddDelay(dl *Delay) bool {
	var (
		err error
		o   orm.Ormer
	)

	dl.Id = tools.GUUID()
	dl.UpdateTime = time.Now().Unix()
	dl.Time = time.Now().Unix()

	o = orm.NewOrm()
	o.Begin()
	// 数据入库
	if _, err = o.Insert(dl); err != nil {
		logs.Error("AddDelay err:", err)
		o.Rollback()
		return false
	}

	// 给设备发送命令
	if err = device.AddDelay(dl); err != nil {
		logs.Error("AddDelay err:", err)
		fmt.Println("rollback:", o.Rollback())
		return false
	}

	o.Commit()
	return true
}

// 更新
func UpdateDelay(dl *Delay) bool {
	var (
		err error
		o   orm.Ormer
		sql string
	)

	dl.UpdateTime = time.Now().Unix()

	o = orm.NewOrm()
	o.Begin()
	// 锁表
	delayData := &Delay{}
	sql = "select * from `delay` where `sta` = ?"
	if err = o.Raw(sql).SetArgs(dl.Sta).QueryRow(delayData); err != nil {
		logs.Error("UpdateDelay error:", err)
		o.Rollback()
		return false
	}

	// 数据入库
	if _, err = o.Update(dl); err != nil {
		logs.Error("UpdateDelay error:", err)
		o.Rollback()
		return false
	}

	// 给设备发送命令
	if err = device.UpdateDelay(dl); err != nil {
		logs.Error("UpdateDelay err:", err)
		o.Rollback()
		return false
	}

	o.Commit()
	return true

}

func DelDelay(dl *Delay) bool {
	var (
		err error
		o   orm.Ormer
		num int64
		res sql.Result
	)
	o = orm.NewOrm()
	o.Begin()
	// 给设备发送命令
	if err = device.DeleteDelay(dl); err != nil {
		logs.Error("DelDelayById err:", err)
		o.Rollback()
		return false
	}

	// 数据入库
	if res, err = o.Raw(`delete from delay where id=?`, dl.Id).Exec(); err != nil {
		logs.Error("DelDelayById error:", err)
		o.Rollback()
		return false
	}
	if num, err = res.RowsAffected(); err != nil || num == 0 {
		logs.Error("DelDelayById error:", err)
		o.Rollback()
		return false
	}

	if num == 0 {
		o.Rollback()
		return false
	}

	o.Commit()
	return true
}

// 判断设备是否已经有延时任务
func IsExistsDelayBySta(sta string) bool {
	return orm.NewOrm().QueryTable(NewDelay().TableName()).Filter("sta", sta).Exist()
}

// 根据sta获取延时任务
func GetDelayBySta(sta string) (*Delay, error) {
	var (
		dl  *Delay
		err error
	)
	dl = &Delay{Sta: sta}
	if err = orm.NewOrm().Read(dl, "sta"); err != nil && err != orm.ErrNoRows {
		logs.Error("GetDelayBySta error:", err)
		return nil, err
	}
	if err == orm.ErrNoRows {
		return nil, nil
	}
	return dl, nil
}

// 根据sta删除延时任务
func DelDelayBySta(sta string) error {
	sql := "DELETE FROM delay WHERE sta = ?"
	_, err := orm.NewOrm().Raw(sql).SetArgs(sta).Exec()
	if err != nil {
		logs.Warn(err)
		return err
	}
	return nil
}
